var imageUploader =  {
	config: {
		cols: 4,
		max: 8,
		placeId: "imageUploader",
		frameId: "imageUploaderFrame",
		actionURL: "../imageuploader/imageuploader.php",
		maxFileSize: '1mb',
		flashSwfURL: '../imageuploader/plupload.flash.swf',
		filters: [
			{title: "Image files", extensions: "jpg,gif,png"}
		],
		resize: {width: 200, height: 200, quality: 90},
		itemPrefix: "imageUploaderItem_"
	},
		
	place: false,
	placeBody: false,
	placeHead: false,
	editor: false, 
	dragObj: false,
	buttonAdd: false,
	dragObjOffset: false,
	dragSource: false,
	startSourcePosition: false,
	dragSourcePosition: false,
	dragPositions: false,
	dragObjects: false,
	editorId: false,
	items: {},
	uploader: false,
	statusBar: false,
	statusBarTotal: false,
	statusBarEach: false,
	statusBarText: false,
	errorBar: false,
	
	$: function(id){
		return document.getElementById(id);
	},
	
	addClass: function(obj, className){
		if (obj.className.indexOf(className)==-1){
			obj.className = obj.className + " " + className;
		}
	},
	
	removeClass: function(obj, className){
		obj.className = obj.className.replace(className,"");
	},
	
	decode: function(text){
		var obj;
		try{
			obj = eval("(" + text + ")");
		} catch(e){
			obj = null;
		}
		return obj;
	},
	
	generateId: function(){
		var flag=true;
		var id = 0;
		while (flag) {
			id = this.config.itemPrefix+Math.floor(Math.random()*1000000);
			if (!this.items[id] || this.items[id]===undefined){
				flag=false;
			}
		}
		return id;
	},
	
	createPlace: function(){
		this.place = document.createElement('TABLE');
		this.placeBody = document.createElement('TBODY');
		this.placeHead = document.createElement('THEAD');
		this.place.className="imageUploader";
		this.place.id = this.config.placeId;
		this.place.appendChild(this.placeHead);
		this.place.appendChild(this.placeBody);
		var errorBar = document.createElement('TD');
		errorBar.colSpan = this.config.cols;
		errorBar.appendChild(this.createErrorBar());
		var button = document.createElement('TD');
		button.appendChild(this.createUploadButton());
		var statusBar = document.createElement('TD');
		statusBar.colSpan = this.config.cols-1;
		statusBar.appendChild(this.createStatusBar());
		var status = document.createElement('TR');
		status.appendChild(button);
		status.appendChild(statusBar);
		var line = document.createElement('TR');
		line.className = "imageUploader_line";
		for (var i=0; i<this.config.cols; i++){
			var td = document.createElement('TD');
			td.innerHTML = "&nbsp;";
			line.appendChild(td);
		}
		var error = document.createElement('TR');
		error.appendChild(errorBar);
		this.placeHead.appendChild(status);
		this.placeHead.appendChild(error);
		this.placeHead.appendChild(line);
		return this.place; 
	},
	
	createItem: function(id, params){
		var html = '\
			<i class="imageUploader_item_remove">&nbsp;</i>\
			<div class="imageUploader_item">\
				<div class="imageUploader_item_move">&nbsp;</div>\
				<div class="imageUploader_item_pic" style="background-image: url('+params.path+')">&nbsp;</div>\
			</div>\
			<div class="imageUploader_item_note"><input type="text" readonly="readonly" value="'+params.name+'" /></div>\
		';
		return html;
	},
	
	createDragPlace: function(){
		this.dragObj = document.createElement('DIV');
		this.dragObj.className="imageUploader_drag_obj";
		document.body.appendChild(this.dragObj);
	},
	
	createEditor: function(){
		this.editor = document.createElement('TEXTAREA');
		this.editor.maxLength = "250";
		this.editor.onkeydown = function(){
			if (this.value.length> 250) {
				this.value = this.value.substring(0, 250);
			}
		}
		this.editor.className = "imageUploader_editor";
		this.editor.onblur = function(){imageUploader.editStop()};
		document.body.appendChild(this.editor);
		
	},
	
	createUploadButton: function(){
		var button = document.createElement('DIV');
		button.id="imageUploader_button_add_contaner";
		button.className="imageUploader_button_add_contaner";
		this.buttonAdd =  document.createElement('SPAN');
		this.buttonAdd.className = "imageUploader_button_add";
		this.buttonAdd.id = "imageUploader_button_add";
		this.buttonAdd.innerHTML = "Добавить";
		button.appendChild(this.buttonAdd);
		return button;
	},
	
	createStatusBar: function(){
		this.statusBar = document.createElement('DIV');
		this.statusBar.className = "imageUploader_statusbar";
		this.statusBar.id = "imageUploader_statusbar";
		this.statusBarTotal = document.createElement('DIV');
		this.statusBarTotal.className = "imageUploader_statusbar_total";
		this.statusBarEach = document.createElement('DIV');
		this.statusBarEach.className = "imageUploader_statusbar_each";
		this.statusBarText = document.createElement('DIV');
		this.statusBarText.className = "imageUploader_statusbar_text";
		this.statusBar.appendChild(this.statusBarTotal);
		this.statusBar.appendChild(this.statusBarEach);
		this.statusBar.appendChild(this.statusBarText);
		return this.statusBar;
	},
	
	createErrorBar: function(){
		this.errorBar = document.createElement('DIV');
		this.errorBar.className = "imageUploader_errorbar";
		this.errorBar.title = "Для скрытия панели дважды кликните мышью.";
		this.errorBar.ondblclick = function(){imageUploader.hideErrorBar()};
		return this.errorBar;
	},
	
	getRows: function(){
		return this.placeBody.childNodes; 
	},
	
	lastRow: function(){
		return this.placeBody.lastChild;
	},
	
	parentRow: function(col){
		return col.parentNode;
	},
	
	createRow: function(){
		var row = document.createElement('TR');
		return row;
	},
	
	addRow: function(row){
		this.placeBody.appendChild(row);
	},
	
	removeRow: function(row){
		this.placeBody.removeChild(row);
	},
	
	getCols: function(row){
		return row.childNodes; 
	},
	
	getColsCount: function(row){
		return row.childNodes.length;
	},
	
	lastCol: function(row){
		return row.lastChild;
	},
	
	firstCol: function(row){
		return row.firstChild;
	},
	
	createCol: function(params){
		var col =  document.createElement('TD');
		col.id=params.id//this.generateId();
		col.innerHTML = this.createItem(col.id, params);
		eval('col.getElementsByTagName("i")[0].onclick = function(){imageUploader.del("'+col.id+'")}');
		eval('col.getElementsByTagName("div")[0].onmousedown = function(e){imageUploader.dragStart("'+col.id+'",e)}');
		eval('col.getElementsByTagName("input")[0].onfocus = function(){imageUploader.editStart("'+col.id+'")}');
		return col;
	},
	
	addCol: function(row, col){
		row.appendChild(col);
	},
	
	removeCol: function(row, col){
		row.removeChild(col);
	},
	
	shiftCol: function(rowSrc, rowDst){
		rowDst.appendChild(this.firstCol(rowSrc));
	},
	
	unShiftCol: function(rowSrc, rowDst){
		rowDst.insertBefore(this.lastCol(rowSrc),this.firstCol(rowDst));
	},
	
	clear: function(){
		this.items = {};
		this.placeBody.innerHTML = '';
	},
	
	add: function(params){
		var col = this.createCol(params);
		var lastRow =  this.lastRow();
		if (!lastRow || this.getColsCount(lastRow)>=this.config.cols) {
			lastRow = this.createRow();
			this.addRow(lastRow);
		}
		this.addCol(lastRow, col);
	},
	
	remove: function(id){
		var col = this.$(id);
		var row = this.parentRow(col);
		this.removeCol(row, col);
		if (this.getColsCount(row)==0) {
			this.removeRow(row);
		} else {
			var rows =  this.getRows();
			for (var i=rows.length-1; i>-1 && rows[i]!=row; i--) {
				this.shiftCol(rows[i],rows[i-1]);
				if (this.getColsCount(rows[i])==0) {
					this.removeRow(rows[i]);
				}
			}
		}
		
	},
	
	move: function(srcPos, dstPos){
		var src = this.dragObjects[srcPos];
		var dst = this.dragObjects[dstPos];
		var dstRow = this.parentRow(dst);
		var srcRow = this.parentRow(src);
		var dstNextNode = dst.nextSibling;
		var rows = this.getRows();
		var dstRowIndex = -1;
		var srcRowIndex = -1;
		for (var i=0; i<rows.length && (dstRowIndex==-1 || srcRowIndex==-1); i++){
			if (rows[i]==srcRow){
				srcRowIndex=i;
			}
			if (rows[i]==dstRow){
				dstRowIndex=i;
			}
		}
		if (srcPos<dstPos){
			if (dstNextNode && dstNextNode!=undefined){
				dstRow.insertBefore(src, dstNextNode);
			} else {
				dstRow.appendChild(src);
			}
		} else {
			dstRow.insertBefore(src, dst);
		}
		if (dstRowIndex>srcRowIndex) {
			for (var i=dstRowIndex; i>srcRowIndex; i--) {
				this.shiftCol(rows[i],rows[i-1]);
			}
		} else if (srcRowIndex>dstRowIndex) {
			for (var i=dstRowIndex; i<srcRowIndex; i++) {
				this.unShiftCol(rows[i],rows[i+1]);
			}
		}
		this.dragObjects.splice(srcPos,1);
		this.dragObjects.splice(dstPos,0,src);
		this.dragSourcePosition = this.dragPositions[dstPos];
	},
	
	getOrder: function(){
		var images =  new Array();
		var length = this.dragObjects.length;
		for (var i=0; i<length; i++) {
			images[i] = this.dragObjects[i].id;
		}
		return images;
	},
	
	cancelEvent: function(){
		return false;
	},
	
	getPosition: function(obj){
		var t=l=0;
		var o=obj;
		while(o) {
			t+=o.offsetTop;
			l+=o.offsetLeft;
			o=o.offsetParent;
		}
		return {t: t,l: l,b: t+obj.offsetHeight,r: l+obj.offsetWidth}
	},
	
	
	dragStart: function(id,e){
		if (!e) e = window.event;
		this.dragSource = this.$(id);
		this.addClass(this.dragSource,"imageUploader_drop_place");
		this.dragObj.innerHTML = this.dragSource.innerHTML;
		this.dragObj.style.display="block";
		this.dragPositions = new Array();
		this.dragObjects = new Array();
		var tds = this.placeBody.getElementsByTagName('td');
		
		for (var i=0; i<tds.length; i++){
			this.dragPositions[i] = this.getPosition(tds[i]);
			this.dragPositions[i].n = i;
			this.dragObjects[i] = tds[i];
			if (tds[i]==this.dragSource){
				this.dragSourcePosition = this.dragPositions[i];
				this.startSourcePosition = this.dragSourcePosition;
			}
		}
		
		var st = e.clientY + Math.max(document.body.scrollTop,document.documentElement.scrollTop);
		var sl = e.clientX + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft);

		this.dragOffset = {
			t: this.dragSourcePosition.t - st,
			l: this.dragSourcePosition.l - sl
		};

		this.addClass(document.body,"imageUploader_no_select");
		document.onmousemove = function(e) {imageUploader.dragMove(e)};
		document.onmouseup = function(e) {imageUploader.dragEnd(e)};
		document.onselectstart = this.cancelEvent;
		this.dragMove(e);
		return false;
	},
	
	dragMove: function(e){
		if (!e) e = window.event;
		var st = e.clientY + Math.max(document.body.scrollTop,document.documentElement.scrollTop);
		var sl = e.clientX + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft);
		this.dragObj.style.left = sl + this.dragOffset.l + 'px';
		this.dragObj.style.top = st + this.dragOffset.t + 'px';
		for (var i=0; i<this.dragPositions.length; i++){
			var tdPos = this.dragPositions[i];
			if (st>tdPos.t && st<tdPos.b && sl>tdPos.l && sl<tdPos.r && this.dragSourcePosition.n!=tdPos.n){
				this.move(this.dragSourcePosition.n,tdPos.n);
			}
		}
		return false;
	},
	
	dragEnd: function(e){
		document.onmousemove = null;
		document.onmouseup = null;
		if (this.startSourcePosition != this.dragSourcePosition){
			this.sendOrder();
		}
		this.removeClass(document.body,"imageUploader_no_select");
		this.dragObj.innerHTML = "";
		this.dragObj.style.display = "none";
		this.removeClass(this.dragSource,"imageUploader_drop_place");
		this.dragSource = false;
		this.dragSourcePosition = false;
		this.dragPositions = false;
		this.dragObjects = false;
		this.dragObjOffset = false;
		return false;
	},
	
	editStart: function(id){
		this.editorId = id;
		var input = this.$(id).getElementsByTagName('input')[0];
		var inputPosition = this.getPosition(input);
		this.editor.style.left = inputPosition.l + 'px';
		this.editor.style.top = inputPosition.t + 'px';
		this.editor.value = input.value;
		this.addClass(this.editor,"imageUploader_editor_show");
		this.editor.focus();
	},
	
	editStop: function(){
		var field = this.$(this.editorId).getElementsByTagName('input')[0];
		if (field.value!=this.editor.value) {
			this.addClass(field.parentNode,"imageUploader_item_note_unsaved");
			field.value = this.editor.value;
			this.rename(this.editorId,field.value);
		}
		this.removeClass(this.editor,"imageUploader_editor_show");
		this.editorId = false;
	},
	
	sendRequest: function(action, success, params){
		if (params) {
			params.action = action;
		} else {
			params = {action: action}
		}
		Ext.Ajax.request({
		   url: this.config.actionURL,
		   success: (success)?this.successRequest:null,
		   failure: this.failureRequest,
		   successCallBack: success,
		   params: params
		});
	},

	successRequest: function(response, opts){
		if (response.responseText && opts.successCallBack){
			var obj = imageUploader.decode(response.responseText);
			if (obj && obj.result) {
				opts.successCallBack(obj.result);
			} else if (obj && obj.error){
				imageUploader.showError(obj.error.code, obj.error.message);
			} else {
				imageUploader.showError(9999);
			}
		} else {
			imageUploader.showError(-200);
		}
	},
	
	failureRequest: function(responce, opts){
		this.showError(1);
	},
	
	load: function(){
		this.sendRequest(
			"get_images",
			this.loadSuccess,
			false
		);
	},
	
	reload: function(){
		imageUploader.clear();
		this.load();
	},
	
	loadSuccess: function(obj){
		for (var i=0; i<obj.length; i++){
			imageUploader.add(obj[i]);
		}
	},
	
	sendOrder: function(){
		this.sendRequest(
			"save_order",
			false,
			{order:this.getOrder()}
		);
	},

	del: function(id){
		this.sendRequest(
			"delete_image",
			this.delSuccess,
			{id:id}
		);
	},
	
	delSuccess: function(obj){
		if (obj.id) {
			imageUploader.remove(obj.id);
		}
	},
	
	rename: function(id, name){
		this.sendRequest(
			"rename_image",
			this.renameSuccess,
			{
				id:id, 
				name: name
			}
		);
	},
	
	renameSuccess: function(obj){
		if (obj.id) {
			try{
				var field = imageUploader.$(obj.id).getElementsByTagName('input')[0];
				imageUploader.removeClass(field.parentNode,"imageUploader_item_note_unsaved");
			} catch(e){}
		}
	},
	
	initPlupload: function(){
		this.uploader = new plupload.Uploader({
			runtimes: 'html5,flash,html4',
			browse_button: 'imageUploader_button_add',
			container: 'imageUploader_button_add_contaner',
			//TODO подумать о выделении области для бросания фоток
			//drop_element: 'imageUploader_button_add',
			max_file_size: this.config.maxFileSize,
			url: this.config.actionURL,
			flash_swf_url : this.config.flashSwfURL,
			filters: this.config.filters,
			resize: this.config.resize
		});
		this.uploader.bind('Init', function(up, params) {
			//alert(params.runtime);
		});
		this.uploader.bind('FilesAdded', function(up, files) {
			up.refresh();
		});
		this.uploader.bind('QueueChanged', function(up) {
			if (up.files.length>0){
				up.start();
				imageUploader.addClass(imageUploader.statusBar,"imageUploader_statusbar_show");
			}
		});
		this.uploader.bind('UploadProgress', function(up, file) {
			var total = imageUploader.uploader.files.length;
			var number = total - up.total.queued;
			imageUploader.statusBarText.innerHTML = 'Загружается файл "'+file.name+'" ('+number+' из '+total+')';
			imageUploader.statusBarEach.style.width = file.percent + '%';
			imageUploader.statusBarTotal.style.width = Math.round(number/total * 100) + '%';
		});
		this.uploader.bind('FileUploaded', function(up, file, response) {
			var flagError = false;
			var robj = false;
			if (response && response.response){
				robj = imageUploader.decode(response.response);
				if (robj){
					if (robj.result){
						imageUploader.add(robj.result);
					} else {
						flagError = true;
					}
				} else {
					flagError = true;
				}
			} else {
				flagError = true;
			}
			if (flagError){
				if (robj && file) {
					imageUploader.addError(robj.error.code,file.name);
				} else if (file) {
					imageUploader.addError(-9999,file.name);
				}
			}
		});
		this.uploader.bind('UploadComplete', function(up, files) {
			imageUploader.statusBarEach.style.width = '0%';
			imageUploader.statusBarTotal.style.width = '0%';
			imageUploader.statusBarText.innerHTML = '';
			imageUploader.removeClass(imageUploader.statusBar,"imageUploader_statusbar_show");
			up.splice(0,files.length);
			up.total.reset();
			up.refresh();
		});
		this.uploader.bind('Error',function(up,error){
			imageUploader.addError(error.code,error.file.name);
		});
		this.uploader.init();
	},
	
	showErrorBar: function(){
		this.errorBar.innerHTML = "";
		this.addClass(this.errorBar,"imageUploader_errorbar_show");
	},
	
	hideErrorBar: function(){
		this.removeClass(this.errorBar,"imageUploader_errorbar_show");
	},
	
	showError: function(code, fileName){
		this.hideErrorBar();
		this.addError(code, fileName);
	},
	
	addError: function(code, fileName){
		if (this.errorBar.className.indexOf("imageUploader_errorbar_show")==-1){
			this.showErrorBar();
		}
		var text = false;
		try {
			code = Number(code);
		} catch(e){}
		if (!fileName || fileName==undefined){
			fileName="";
		}
		switch (code) {
			case -9999: //Неопознаная ошибка
				text = fileName + " возникла ошибка;";
				break;
			case -200:
				text = fileName + " ошибка доступа к серверу;";
				break;
			case -300:
				text = fileName + " ошибка чтения;";
				break;
			case -400:
				text = fileName + " нет прав доступа;";
				break;
			case -600:
				text = fileName + " превышает максимальный размер;";
				break;
			case -601:
				text = fileName + " расширение файла недопустимо;";
				break;
			case -700:
				text = fileName + " формат фотографии не распознан;";
				break;
			case -701:
				text = fileName + " на обработку фотографии не хватило памяти;";
				break;
			case -702:
				text = fileName + " не допустимое разрешение фотографии;";
				break;
			
			case 1:
				text = "Сервер не отвечает на запрос.";
				break;
			case 100:
				text = fileName + " ошибка загрузки;";
				break;
			case 110: 
				text = "Не удалось удалить фотографию.";
				break;
			case 120: 
				text = "Не удалось сменить подпись к фотографии.";
				break;
			case 130:
				text = "Не возможно получить список картинок.";
				break;
			case 140:
				text = "Ошибка сохранения порядка фотографий.";
				break;
		}
		if (text=="") {
			text = "В ходе выполнения произошел сбой.";
		}
		var block = document.createElement('DIV');
		block.innerHTML = text;
		this.errorBar.appendChild(block);
	},
	
	init: function(params){
		if (params && params.id) {
			this.config.actionURL += "?globalId=" + params.id;
		}
		if (params && params.parentId && params.parentId!=undefined){
			
			this.$(params.parentId).appendChild(this.createPlace());
		} else {
			document.body.appendChild(this.createPlace());
		}
		this.createDragPlace();
		this.createEditor();
		this.initPlupload();
	}
}